package com.pla.clipboardimagepublisher;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.MessageFormat;
import java.util.prefs.Preferences;
import javax.imageio.ImageIO;

public class ClipboardImagePublisher {
  public static void launchUrl(String urlString) throws IOException {
    MessageFormat launchUrlMessageFormat = new MessageFormat("cmd /C start \"url\" \"{0}\"");
    Object[] objects = { urlString };
    processCommand(launchUrlMessageFormat.format(objects));
  }

  public static void main(String[] args) throws Exception {
    ClipboardImagePublisher cip = new ClipboardImagePublisher();
    cip.publish();
    launchUrl(cip.getLocalTemporaryAbsolutePath());
    launchUrl("http://patrickarchibald.com/pictures/" + cip.getPublishedFileName());
    System.exit(0);
  }

  private static void processCommand(String commandString) throws IOException {
    Runtime run = Runtime.getRuntime();
    run.exec(commandString);
  }

  private Clipboard clipboard;
  private final String CRLF = "\r\n";
  private int height;
  private String localTemporaryAbsolutePath;
  private String localTemporaryFileName;
  private String publishedFileName;
  private int width;
  private Preferences preferences;

  public ClipboardImagePublisher() {
    clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    preferences = Preferences.userNodeForPackage(this.getClass());
  }

  private void close(BufferedReader bufferedReader) {
    if (bufferedReader != null) {
      try {
        bufferedReader.close();
      }
      catch (Exception e) {
      }
    }
  }

  private void close(InputStream inputStream) {
    if (inputStream != null) {
      try {
        inputStream.close();
      }
      catch (Exception e) {
      }
    }
  }

  private void close(OutputStream outputStream) {
    if (outputStream != null) {
      try {
        outputStream.close();
      }
      catch (Exception e) {
      }
    }
  }

  public int getHeight() {
    return height;
  }

  public String getLocalTemporaryAbsolutePath() {
    return localTemporaryAbsolutePath;
  }

  public String getLocalTemporaryFileName() {
    return localTemporaryFileName;
  }

  public String getPublishedFileName() {
    return publishedFileName;
  }

  public int getWidth() {
    return width;
  }

  public String publish() throws Exception {
    if (localTemporaryFileName == null) {
      writeLocalTemporaryFile();
    }
    OutputStream outputStream = null;
    BufferedReader bufferedReader = null;
    InputStream inputStream = null;
    FileInputStream fileInputStream = null;
    DataOutputStream dataOutputStream = null;
    StringBuffer fileName = new StringBuffer();
    fileName.append("clipboardimagepublisher");
    fileName.append(System.currentTimeMillis());
    fileName.append(width * height);
    fileName.append(".png");
    publishedFileName = fileName.toString();
    String hostName = preferences.get(PreferencesDialog.HOST_NAME, "patrickarchibald.com");
    String servletPath = preferences.get(PreferencesDialog.SERVLET_PATH,
        "/servlet/com.pla.ClipboardImagePublisherServlet");
    URL url = new URL("http://" + hostName + servletPath);
    URLConnection connection = url.openConnection();
    connection.setDoInput(true);
    connection.setDoOutput(true);
    connection.setUseCaches(false);
    connection.setDefaultUseCaches(false);
    String boundary = "---------------------------" + System.currentTimeMillis();
    connection.setRequestProperty("Connection", "Keep-Alive");
    connection.setRequestProperty("HTTP_REFERER", "http://" + hostName);
    connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="
        + boundary.substring(2));
    dataOutputStream = new DataOutputStream(connection.getOutputStream());
    File file = new File(fileName.toString());
    dataOutputStream.writeBytes(boundary);
    dataOutputStream.writeBytes(CRLF);
    dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"theFile");
    dataOutputStream.writeBytes("\"; filename=\"");
    dataOutputStream.writeBytes(file.getName());
    dataOutputStream.writeBytes("\"");
    dataOutputStream.writeBytes(CRLF);
    dataOutputStream.writeBytes("Content-Type: application/octet-stream");
    dataOutputStream.writeBytes(CRLF);
    dataOutputStream.writeBytes(CRLF);
    fileInputStream = new FileInputStream(localTemporaryAbsolutePath);
    byte[] bytes = new byte[1000];
    int cnt = fileInputStream.read(bytes);
    int totalBytes = 0;
    while (cnt == bytes.length) {
      totalBytes += cnt;
      dataOutputStream.write(bytes, 0, cnt);
      cnt = fileInputStream.read(bytes);
    }
    dataOutputStream.write(bytes, 0, cnt);
    totalBytes += cnt;
    dataOutputStream.writeBytes(CRLF);
    dataOutputStream.writeBytes(boundary);
    dataOutputStream.writeBytes("--");
    dataOutputStream.writeBytes(CRLF);
    dataOutputStream.writeBytes(CRLF);
    dataOutputStream.flush();
    dataOutputStream.close();
    fileInputStream.close();
    inputStream = connection.getInputStream();
    bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    String line = bufferedReader.readLine();
    System.out.println("Recieved from servlet: " + line);
    close(outputStream);
    close(bufferedReader);
    close(inputStream);
    close(fileInputStream);
    close(dataOutputStream);
    return line;
  }

  public void setPublishedFileName(String publishedFileName) {
    this.publishedFileName = publishedFileName;
  }

  public void writeLocalTemporaryFile() throws Exception {
    Transferable transferable = clipboard.getContents(null);
    Image image = null;
    try {
      image = (Image) transferable.getTransferData(DataFlavor.imageFlavor);
    }
    catch (UnsupportedFlavorException e) {
      throw new Exception("Clipboard does not contain an image. "
          + "Try pressing the Print Screen button first.");
    }
    BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null),
        BufferedImage.TYPE_INT_RGB);
    Graphics2D g = bufferedImage.createGraphics();
    g.drawImage(image, 0, 0, null);
    g.dispose();
    File localTemporaryFile = File.createTempFile("ClipboardImagePublisher", ".png");
    System.out.println(localTemporaryFile.getAbsolutePath());
    localTemporaryAbsolutePath = localTemporaryFile.getAbsolutePath();
    localTemporaryFileName = localTemporaryFile.getName();
    ImageIO.write(bufferedImage, "png", localTemporaryFile);
    height = bufferedImage.getHeight();
    width = bufferedImage.getWidth();
  }
}